/*
 * CMichatDb.h
 *
 *  Created on: 2011-2-22
 *      Author: Administrator
 */

#ifndef CMICHATDB_H_
#define CMICHATDB_H_

#include <ystring.h>
#include <d32dbms.h>
#include <map>
#include <vector>
#include <list>
#include "ylog.h"
class RDbNameDatabase;
class RFs;

struct TableColumn
{
    TableColumn(const YString &aColName, TDbColType aType, TUint aAttrib):
        iColName(aColName)
    {
        iColType = aType;
        iAttributes = aAttrib;
    }
    
    YString iColName;
    TDbColType iColType;
    TUint iAttributes; //EAutoIncrement or ENotNull
};

class TableDesC
{
public:
    
    typedef std::vector<TableColumn>::const_iterator column_iterator;
    
    TableDesC(){}
    TableDesC(const char * aTableName): iTableName(aTableName)
    {}
    
    void AddColumn(const char * aColName, TDbColType aType, TUint aAttrib = 0)
    {
        columns.push_back(TableColumn(YString(aColName), aType, aAttrib));
    }
    
    const YString& GetName() const
    {
        return iTableName;
    }
    
    TDbColType GetColType(TInt aIdx) const
    {
        return columns[aIdx].iColType;
    }
    
    column_iterator begin() const
    {
        return columns.begin();
    }
    
    column_iterator end() const
    {
        
    	return columns.end();
    }
    
    void SetName(const char * aTableName)
    {
        iTableName = YString(aTableName);
    }
    //添加
    bool IsEmpty()
    {
    	return columns.empty();
    }
    
private:
    YString iTableName;
    std::vector<TableColumn> columns;
};

struct ColumnValue
{
    union{
        TInt sint;
        TInt32 int32;
        TInt64 int64;
        TUint uint;
        TUint32 uint32;
        TReal32 real32;
        TReal64 real64;
    }val;
    TTime time; 
    YString8 str8;
    YString str16;
};

class TableItem
{
public:
   
    typedef std::map<TInt, ColumnValue>::const_iterator column_iterator;
  
    void SetInt(TInt aIdx, TInt aValue);
    void SetInt32(TInt aIdx, TInt32 aValue);
    void SetInt64(TInt aIdx, TInt64 aValue);
    void SetUint(TInt aIdx, TUint aValue);
    void SetUint32(TInt aIdx, TUint32 aValue);
    void SetReal32(TInt aIdx, TReal32 aValue);
    void SetReal64(TInt aIdx, TReal64 aValue);
    void SetTime(TInt aIdx, const TTime &aValue);
    void SetString8(TInt aIdx, const YString8 &aValue);
    void SetString16(TInt aIdx, const YString &aValue);
    
    TInt GetInt(TInt aIdx) { return values[aIdx].val.sint; }
    TInt32 GetInt32(TInt aIdx) { return values[aIdx].val.int32; }
    TInt64 GetInt64(TInt aIdx) { return values[aIdx].val.int64; }
    TUint GetUint(TInt aIdx) { return values[aIdx].val.uint; } 
    TUint32 GetUint32(TInt aIdx) { return values[aIdx].val.uint32; }
    TReal32 GetReal32(TInt aIdx) { return values[aIdx].val.real32; }
    TReal64 GetReal64(TInt aIdx) { return values[aIdx].val.real64; }
    TTime GetTime(TInt aIdx) { return values[aIdx].time; }
    YString8 & GetString8(TInt aIdx) { return values[aIdx].str8; }
    YString & GetString16(TInt aIdx) { return values[aIdx].str16; } //can't define to be const, why?
    
    column_iterator begin() const
    {
        return values.begin();
    }
    
    column_iterator end() const
    {
        return values.end();
    }
    //idx从1开始计数，与CDbColSet保持一致
    void AddColumnValue(TInt idx, const ColumnValue &cv)
    {
        values[idx] = cv;
    }
   
private:
    std::map<TInt, ColumnValue> values;
};

typedef TableItem ResultItem;
typedef std::list<ResultItem> ResultSet;

class CMichatDbManager : public CBase
{
public:
    
    ~CMichatDbManager();
    
    static CMichatDbManager * GetInstanceL();
    static CMichatDbManager * GetInstanceLC();
    
    static void PutInstance()
    {
        CLogPerformanceItem pA("PutInstance()");
        delete instance;
        instance = NULL;
        pA.EndHere();
    }
    RDbNamedDatabase& GetDatabase();
    void Destroy();
    void CreateTableL(const TableDesC &td);
    void InsertBatchItemsL(const TableDesC &td, const std::vector<TableItem>& tis);
    void InsertItemL(const TableDesC &td, const TableItem &ti);
    void UpdateItemL(const TableDesC &td, const TableItem &ti, const YString &where);
    void UpdateOneColumnL(const YString& tableName,const YString &columnName,const YString& where,const ColumnValue &value,TDbColType type);
    void DeleteItemL(const TableDesC &td, const YString &where = YString(), const YString &order = YString(), int limit = INT_MAX);
    int QueryItemL(const TableDesC &td, const YString &sql, int limit = INT_MAX,int startPosition=0);
    bool IsExists(const TableDesC &td, const YString &where);
    void Compact();
    ResultSet & GetResultSet()
    {
        return rs;
    }
    int GetRecordCount(TableDesC &td);
    void BeginTransaction();
    void EndTransaction();
public:
    void GetColumnValue(TDbColType type, ColumnValue &cv, RDbView &view, TInt idx);
private:
    CMichatDbManager(){}
    void InitDatabaseL();
    /* used by UpdateItemL to set RDbView from ColumnValue */
    void SetViewValue(TDbColType type, RDbView &view, TInt idx, const ColumnValue &cv);
    void SetColumnValue(TDbColType type, ColumnValue &cv, const TAny *data);
    /* used by QueryItemL to get ColumnValue from RDbView */
public: 
    void ReadLongText(TDbColType type, ColumnValue &cv, RDbView &view, TInt idx);
    void WriteLongText(TDbColType type, RDbView &view, TInt idx, const ColumnValue &cv);
private:
    static CMichatDbManager *instance;
    RDbNamedDatabase iMichatDatabase;
    RFs iFsSession;
    ResultSet rs;
};

#endif /* CMICHATDB_H_ */
